/* Includes ------------------------------------------------------------------*/
#include "main.h"
#include "UsrI2C.h"
#include "apm32f00x_i2c.h"
#include "apm32f00x_gpio.h"
#include "apm32f00x_misc.h"

static volatile uint32_t timeStart = 0;
/*!
 * @brief       I2C Init
 *
 * @param       None
 *
 * @retval      None
 */
void I2C_Init(void)
{
    I2C_Config_T i2cConfig;
    GPIO_Config_T gpioConfig;

    // need set 1 first
    GPIO_SetBit(GPIOB, GPIO_PIN_5 | GPIO_PIN_4);
    gpioConfig.mode = GPIO_MODE_OUT_OD;
    gpioConfig.pin = GPIO_PIN_5 | GPIO_PIN_4;
    gpioConfig.speed = GPIO_SPEED_10MHz;
    GPIO_Config(GPIOB, &gpioConfig);

    I2C_Reset();
    I2C_EnableSoftwareReset();
	APM_Delay(100);
	I2C_DisableSoftwareReset();
    APM_Delay(100);

    /* ACK when current byte being received  */
    i2cConfig.ack = I2C_ACK_CURRENT;
    /* Set Address  */
    i2cConfig.addr = 0;
    /* 7-bit address */
    i2cConfig.addrMode = I2C_ADDR_7_BIT;
    /* duty cycle = 2 */
    i2cConfig.dutyCycle = I2C_DUTYCYCLE_2;
    /* Input clock frequency is 48MHZ */
    i2cConfig.inputClkFreqMhz = 48;
    /* Enable buffer and event interrupt */
    i2cConfig.interrupt = I2C_INT_BUFFER | I2C_INT_EVENT;
    /* Output clock frequency is 100KHZ */
    i2cConfig.outputClkFreqHz = 100000;
    I2C_Config(&i2cConfig);

    // NVIC_EnableIRQRequest(IIC_IRQn, 0X01);

    /* Enable I2C */
    I2C_Enable();
}

int HAL_I2C_Master_Transmit(uint16_t DevAddress, uint8_t *pData, uint8_t Size, uint32_t Timeout)
{
    /* Wait bus is idle  */
    timeStart = sysTick;
    while (I2C_ReadStatusFlag(I2C_FLAG_BUSBUSY) == SET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -1;
    }

    /* Generate a start condition */
    I2C_EnableGenerateStart();

    /* Start condition generated */
    while (I2C_ReadStatusFlag(I2C_FLAG_START) == RESET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -2;
    }

    I2C_TxAddress7Bit(DevAddress, I2C_DIRECTION_TX);

    /* Received address matched */
    while (I2C_ReadStatusFlag(I2C_FLAG_ADDR) == RESET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -3;
    }

    (void)I2C->STS3;
    uint8_t dataBufPt = 0;
    /* Wait end of transmission */
    while (dataBufPt <= Size)
    {
        /* STS1_TXBEF = 1 and STS3_RWMF = 1 */
        if (I2C_ReadStatusFlag(I2C_FLAG_RWMF | I2C_FLAG_TXBE) == SET)
        {
            if (dataBufPt == Size)
            {
                /* Stop condition generated */
                I2C_EnableGenerateStop();
            }
            else
            {
                I2C_TxData(pData[dataBufPt]);
            }
            dataBufPt++;
        }
        if ((sysTick - timeStart) > Timeout)
            return -4;
    }
    /* Wait bus is idle  */
    while (I2C_ReadStatusFlag(I2C_FLAG_BUSBUSY) == SET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -5;
    }
    return 0;
}

int HAL_I2C_Master_Receive(uint16_t DevAddress, uint8_t *pData, uint8_t Size, uint32_t Timeout)
{
    /* Wait bus is idle  */
    timeStart = sysTick;
    while (I2C_ReadStatusFlag(I2C_FLAG_BUSBUSY) == SET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -1;
    }
    /* Generate a start condition */
    I2C_EnableGenerateStart();

    /* Start condition generated */
    while (I2C_ReadStatusFlag(I2C_FLAG_START) == RESET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -2;
    }

    /* ACK when current byte being received  */
    I2C_ConfigAcknowledge(I2C_ACK_CURRENT);

    I2C_TxAddress7Bit(DevAddress, I2C_DIRECTION_RX);
    // Received address matched
    while (I2C_ReadStatusFlag(I2C_FLAG_ADDR) == RESET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -3;
    }
    (void)I2C->STS3;
    uint8_t dataBufPt = 0;
    /* Wait end of reception */
    while (dataBufPt < Size)
    {
        /* STS1_RXBNEF = 1 and STS3_RWMF = 0 */
        if ((I2C_ReadStatusFlag(I2C_FLAG_RXBNE) == SET) && (I2C_ReadStatusFlag(I2C_FLAG_RWMF) == RESET))
        {
            pData[dataBufPt++] = I2C_RxData();
            if (dataBufPt == Size)
            {
                I2C_ConfigAcknowledge(I2C_ACK_NONE);
                I2C_EnableGenerateStop();
            }
        }
        if ((sysTick - timeStart) > Timeout)
            return -4;
    }
    /* Wait bus is idle  */
    while (I2C_ReadStatusFlag(I2C_FLAG_BUSBUSY) == SET)
    {
        if ((sysTick - timeStart) > Timeout)
            return -5;
    }
    return 0;
}

static uint8_t wtdata[4] = {0};
int i2c_w_reg(uint8_t dev_adr, uint8_t addr, uint8_t data)
{
    int ret = 0;
    wtdata[0] = addr;
    wtdata[1] = data;
    ret = HAL_I2C_Master_Transmit(dev_adr, wtdata, 2, 10);
    return ret;
}

int i2c_w_regs(uint8_t dev_adr, uint8_t *data, uint16_t len)
{
    int ret = 0;
    ret = HAL_I2C_Master_Transmit(dev_adr, data, len, 10);
    return ret;
}

int i2c_r_reg(uint8_t dev_adr, uint8_t addr, uint8_t *buf, uint16_t len)
{
    int ret = 0;
    wtdata[0] = addr;
    ret = HAL_I2C_Master_Transmit(dev_adr, wtdata, 1, 10);
    if (ret != 0)
        return ret;
    ret = HAL_I2C_Master_Receive(dev_adr, buf, len, 10 * len);
    return ret;
}
